package client

import (
	"context"
	"fmt"
	"gitee.com/igolang/imoney/internal/core/logger"
	"gitee.com/igolang/pkg/xcfg"
	"gitee.com/igolang/pkg/xredis"
	"github.com/pkg/errors"
	"sync"
)

var rc = &redisClient{
	clients: make(map[string]*xredis.Client),
}

type redisClient struct {
	clients map[string]*xredis.Client
	sync.RWMutex
}

func (c *redisClient) add(name string, client *xredis.Client) {
	c.Lock()
	defer c.Unlock()
	c.clients[name] = client
}

func (c *redisClient) get(name string) *xredis.Client {
	c.RLock()
	defer c.RUnlock()
	return c.clients[name]
}

func (c *redisClient) close() error {
	c.Lock()
	defer c.Unlock()
	errs := make([]error, 0)
	for _, v := range c.clients {
		if v == nil {
			continue
		}
		if err := v.Close(); err != nil {
			errs = append(errs, err)
		}
	}
	if len(errs) > 0 {
		return errors.Errorf("%+v", errs)
	}
	return nil
}

func (c *redisClient) Init() error {
	xredis.SetLogger(&redisLogger{})
	name := DefaultRedis
	key := "redis." + name
	if !xcfg.IsSet(key) {
		return errors.New("redis config nil")
	}

	config := &xredis.RedisConfig{}
	if err := xcfg.UnmarshalKey(key, config); err != nil {
		return errors.Errorf("parse redis config err: %v", err)
	}
	client, err := xredis.NewClient(config)
	if err != nil {
		return err
	}
	if config.KeyPrefix != "" {
		client.EnableKeyPrefix()
	}
	c.add(name, client)
	return nil
}

func (c *redisClient) Shutdown() error {
	return c.close()
}

func Redis(names ...string) *xredis.Client {
	name := DefaultRedis
	if len(names) > 0 {
		name = names[0]
	}
	return rc.get(name)
}

func SetRedisClient(name string, client *xredis.Client) {
	rc.add(name, client)
}

type redisLogger struct {
}

func (l *redisLogger) Printf(ctx context.Context, format string, v ...interface{}) {
	logger.Log().InfoContext(ctx, fmt.Sprintf(format, v))
}
